package yana.tpe.shop.domain.dao.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import yana.tpe.shop.domain.dao.TradeDao;
import yana.tpe.shop.domain.domains.Product;
import yana.tpe.shop.domain.domains.Seller;
import yana.tpe.shop.domain.domains.Trade;
import yana.tpe.shop.domain.domains.TradeElement;


public class TradeDaoImpl extends AbstractDaoImpl<Trade> implements TradeDao {

    public TradeDaoImpl(AccountBookDao accountBookDao) {
        super(accountBookDao);
    }

    @Override
    protected Class<Trade> getDomainClass() {
        return Trade.class;
    }

    @Override
    public List<Trade> selectProductInRange(String productName, Date start, Date end) {
        List<Trade> list = list();

        m1:
        for (Iterator<Trade> it = list.iterator(); it.hasNext();) {
            Trade trade = it.next();
            Date date = trade.getDate();
            
            if (date.before(end) && date.after(start)) {
                for (TradeElement te : trade.getElements()) {
                    if (te.getProduct().getName().equals(productName)) {
                        continue m1;
                    }
                }
            }

            it.remove();
        }

        return list;
    }

    @Override
    public List<Product> select10BestSelingProduct() {
        Map<Product, Double> map = new HashMap<Product, Double>();

        for(Trade trade : list()) {
            for(TradeElement element : trade.getElements()) {
                Product product = element.getProduct();

                if (!map.containsKey(product)) {
                    map.put(product, 0.0);
                }

                map.put(product, element.getAmount() + map.get(product));
            }
        }

        Set<Map.Entry<Product, Double>> set = new TreeSet<Map.Entry<Product, Double>>(
                new Comparator<Map.Entry<Product, Double>>(){

            @Override
            public int compare(Entry<Product, Double> o1, Entry<Product, Double> o2) {
                int compare = Double.compare(o1.getValue(), o2.getValue());
                return compare == 0 ? -1 : compare;
            }
        });
        set.addAll(map.entrySet());

        List<Product> list = new ArrayList<Product>(10);

        int i = 0;
        for (Entry<Product, Double> entry : set) {
            list.add(entry.getKey());
            if (i ++ == 9) {
                break;
            }
        }

        return list;
    }

    @Override
    public Seller selectBestSeller() {
        Map<Seller, Integer> map = new HashMap<Seller, Integer>();

        for(Trade trade : list()) {
            Seller seller = trade.getSeller();

            if (!map.containsKey(seller)) {
                map.put(seller, 0);
            }

            map.put(seller, 1 + map.get(seller));
        }
        
        if (map.isEmpty()) {
            return null;
        }


        Set<Map.Entry<Seller, Integer>> set = new TreeSet<Map.Entry<Seller, Integer>>(
                new Comparator<Map.Entry<Seller, Integer>>(){

            @Override
            public int compare(Entry<Seller, Integer> o1, Entry<Seller, Integer> o2) {
                return o1.getValue() <= o2.getValue() ? -1 : 1;
            }
        });
        set.addAll(map.entrySet());

        return set.iterator().next().getKey();
    }


}
